﻿using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using VM.Core;
using VM.PlatformSDKCS;
using VMControls.RenderInterface;
using VisionDesigner;


namespace Vision.roi
{
    public class roi
    {

        /// <summary>
        /// 设置矩形ROI
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="ModuleName"></param>
        public void SetRectROI(IRectROI rect, string ModuleName)
        {
            RoiBox roiBox = CreateRoiBox(rect);
            SetRoi(roiBox, ModuleName, "RoiType");
        }

        /// <summary>
        /// 设置圆环ROI
        /// </summary>
        /// <param name="circleCaliper"></param>
        /// <param name="ModuleName"></param>
        public void SetCircleROI(ICircleROI circleROI, string ModuleName)
        {
            RoiAnnulus roiAnnulus = CreateRoiAnnulus(circleROI);
            SetRoi(roiAnnulus, ModuleName, "RoiType");
        }

        /// <summary>
        /// 设置圆卡尺ROI
        /// </summary>
        /// <param name="circleCaliper"></param>
        /// <param name="ModuleName"></param>
        public void SetCircleCaliperROI(ICircleCaliperROI circleCaliper, string ModuleName)
        {
            RoiCircleCaliper roiCircleCaliper = CreateRoiCircleCaliper(circleCaliper);
            SetRoi(roiCircleCaliper, ModuleName, "RoiType");
        }


        /// <summary>
        /// 设置多边形ROI
        /// </summary>
        /// <param name="polygon"></param>
        /// <param name="ModuleName"></param>
        public void SetPolygonROI(IPolygonROI polygon, string ModuleName)
        {

            // 设置ROI           
            RoiPolygon roiPolygon = CreateRoiPolygon(polygon);
            SetRoi(roiPolygon, ModuleName, polygon.GetType().ToString() == "Apps.Data.NormalizedPolygonMaskROIModel" ? "ExternRoiType" : "RoiType");
        }

        /// <summary>
        /// 设置直线卡尺ROI
        /// </summary>
        /// <param name="lineCaliper"></param>
        /// <param name="ModuleName"></param>
        public void SetLineCaliperROI(ILineCaliperROI lineCaliper, string ModuleName)
        {
            // 设置ROI  
            RoiLineCaliper roiLineCaliper = CreateRoiLineCaliper(lineCaliper);
            SetRoi(roiLineCaliper, ModuleName, "RoiType");
        }

        /// <summary>
        /// 设置圆弧卡尺ROI
        /// </summary>
        /// <param name="sectorCaliper"></param>
        /// <param name="ModuleName"></param>
        public void SetSectorCaliperROI(ISectorCaliperROI sectorCaliper, string ModuleName)
        {
            // 设置ROI  
            RoiSectorCaliper roiSectorCaliper = CreateRoiSectorCaliper(sectorCaliper);
            SetRoi(roiSectorCaliper, ModuleName, "RoiType");
        }

        public void SetMultiROI(List<IROI> roiList, string ModuleName)
        {
            // 计算需要分配的总内存大小
            int roiSize = CalculateTotalSize(roiList);

            // 分配内存
            IntPtr ptr = Marshal.AllocHGlobal(roiSize);

            // 将 ROI 数据拷贝到内存中
            CopyROIToMemory(roiList, ptr);

            // 获取模块 ID
            VmModule module = (VmModule)VmSolution.Instance[ModuleName];
            uint moduleId = module.ID;

            // 设置感兴趣 ROI
            ServerSDKManager.serverSDKManager.mModuleManager.SetBinaryData(moduleId, "RoiType", ptr, roiSize);

            // 释放内存
            Marshal.FreeHGlobal(ptr);
        }

        // 计算需要分配的总内存大小
        private int CalculateTotalSize(List<IROI> roiList)
        {
            int totalSize = 0;

            foreach (var item in roiList)
            {
                if (item is IRectROI)
                {
                    totalSize += Marshal.SizeOf<RoiBox>();
                }
                else if (item is ICircleROI)
                {
                    totalSize += Marshal.SizeOf<RoiAnnulus>();
                }
                else if (item is ICircleCaliperROI)
                {
                    totalSize += Marshal.SizeOf<RoiCircleCaliper>();
                }
            }

            return totalSize;
        }

        // 将 ROI 数据拷贝到内存中
        private void CopyROIToMemory(List<IROI> roiList, IntPtr ptr)
        {
            int ptrLocation = 0;

            foreach (var item in roiList)
            {
                if (item is IRectROI rect)
                {
                    RoiBox roiBox = CreateRoiBox(rect);
                    Marshal.StructureToPtr(roiBox, ptr + ptrLocation, false);
                    ptrLocation += Marshal.SizeOf(roiBox);
                }
                else if (item is ICircleROI circleROI)
                {
                    RoiAnnulus roiAnnulus = CreateRoiAnnulus(circleROI);
                    Marshal.StructureToPtr(roiAnnulus, ptr + ptrLocation, false);
                    ptrLocation += Marshal.SizeOf(roiAnnulus);
                }
                else if (item is ICircleCaliperROI circleCaliper)
                {
                    RoiCircleCaliper roiCircleCaliper = CreateRoiCircleCaliper(circleCaliper);
                    Marshal.StructureToPtr(roiCircleCaliper, ptr + ptrLocation, false);
                    ptrLocation += Marshal.SizeOf(roiCircleCaliper);
                }
            }
        }

        // 创建 RoiBox 结构体
        private RoiBox CreateRoiBox(IRectROI rect)
        {
            return new RoiBox
            {
                bRoiType = (byte)RoiType.ROI_TYPE_BOX,
                fCenterX = (float)rect.CenterPoint.X,
                fCenterY = (float)rect.CenterPoint.Y,
                fWidth = (float)rect.Width,
                fHeight = (float)rect.Height,
                fAngle = (float)rect.Angle
            };
        }

        // 创建 RoiAnnulus 结构体
        private RoiAnnulus CreateRoiAnnulus(ICircleROI circleROI)
        {
            return new RoiAnnulus
            {
                bRoiType = (byte)RoiType.ROI_TYPE_ANNULUS,
                stCenterPoint = new RoiPoint { fX = (float)circleROI.CenterPoint.X, fY = (float)circleROI.CenterPoint.Y },
                fInnerRadius = (float)circleROI.MinRadius,
                fOuterRadius = (float)circleROI.Radius,
                fStartAngle = 0.0f,
                fEndAngle = 0.0f
            };
        }

        // 创建 RoiCircleCaliper 结构体
        private RoiCircleCaliper CreateRoiCircleCaliper(ICircleCaliperROI circleCaliper)
        {
            return new RoiCircleCaliper
            {
                bRoiType = (byte)RoiType.ROI_TYPE_CIRCLECALIPER,
                fCenterX = (float)circleCaliper.CenterPoint.X,
                fCenterY = (float)circleCaliper.CenterPoint.Y,
                fWidth = (float)circleCaliper.CaliperWidth,
                fHeight = (float)circleCaliper.CaliperHeight,
                fOutterRadius = (float)circleCaliper.Radius,
                fStartAngle = 0.0f,
                fEndAngle = 0.0f,
                nNum = 10
            };
        }

        // 创建 RoiPolygon 结构体
        private RoiPolygon CreateRoiPolygon(IPolygonROI polygon)
        {
            RoiPolygon roiPolygon = new RoiPolygon
            {
                bRoiType = (byte)RoiType.ROI_TYPE_POLYGON,
                nVertexNum = (uint)polygon.PolygonPoints.Count,
                stVertexPoints = new RoiPoint[ImvsSdkDefine.IMVS_MAX_POLYGON_VERTEX_NUM]
            };

            for (int i = 0; i < roiPolygon.nVertexNum; i++)
            {
                roiPolygon.stVertexPoints[i].fX = (float)polygon.PolygonPoints[i].X;
                roiPolygon.stVertexPoints[i].fY = (float)polygon.PolygonPoints[i].Y;
            }

            return roiPolygon;
        }

        // 创建 RoiLineCaliper 结构体
        private RoiLineCaliper CreateRoiLineCaliper(ILineCaliperROI lineCaliper)
        {
            return new RoiLineCaliper
            {
                bRoiType = (byte)RoiType.ROI_TYPE_LINECALIPER,
                fStartX = (float)lineCaliper.StartPoint.X,
                fStartY = (float)lineCaliper.StartPoint.Y,
                fEndX = (float)lineCaliper.EndPoint.X,
                fEndY = (float)lineCaliper.EndPoint.Y,
                fWidth = (float)lineCaliper.CaliperWidth,
                fHeight = (float)lineCaliper.CaliperHeight,
                fAngle = (float)lineCaliper.CaliperRotateAngle,
                nNum = 10
            };
        }

        // 创建 RoiSectorCaliper 结构体
        private RoiSectorCaliper CreateRoiSectorCaliper(ISectorCaliperROI sectorCaliper)
        {
            return new RoiSectorCaliper
            {
                bRoiType = (byte)RoiType.ROI_TYPE_SECTORCALIPER,
                fStartX = (float)sectorCaliper.StartPoint.X,
                fStartY = (float)sectorCaliper.StartPoint.Y,
                fEndX = (float)sectorCaliper.EndPoint.X,
                fEndY = (float)sectorCaliper.EndPoint.Y,
                fRadius = (float)sectorCaliper.Radius,
                fWidth = (float)sectorCaliper.CaliperWidth,
                fHeight = (float)sectorCaliper.CaliperHeight,
                nNum = 10,     // 卡尺数量
                nLargeArc = sectorCaliper.IsLargeArc ? 1 : 0,  // 是否大圆弧
                nClockWise = sectorCaliper.IsClockwise ? 1 : 0   // 是否顺时针方向
            };
        }


        private void SetRoi<T>(T roi, string moduleName, string roiType)
        {
            IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(roi));
            Marshal.StructureToPtr(roi, ptr, false);
            VmModule module = (VmModule)VmSolution.Instance[moduleName];
            uint moduleId = module.ID;
            ServerSDKManager.serverSDKManager.mModuleManager.SetBinaryData(moduleId, roiType, ptr, CalculateRoiDataSize(roi));
            Marshal.FreeHGlobal(ptr);
            ptr = IntPtr.Zero;
        }

        private int CalculateRoiDataSize<T>(T roi)
        {
            int dataSize = Marshal.SizeOf(roi);
            if (roi is RoiPolygon)
            {
                RoiPolygon polygon = (RoiPolygon)(object)roi;
                dataSize -= (ImvsSdkDefine.IMVS_MAX_POLYGON_VERTEX_NUM - (int)polygon.nVertexNum) * Marshal.SizeOf(polygon.stVertexPoints[0]);
            }
            return dataSize;
        }

    }
}





